#ifndef _GRAPH_H_
#define _GRAPH_H_ 1

#include <iostream>
#include <vector>
template <typename T> class graph_adjmatrix
{
  private:
    std::vector<T> vertexes;
    std::vector<std::vector<T>> adjmatrix;

  public:
    graph_adjmatrix(const std::vector<T> &vertexes, const std::vector<std::vector<T>> edges);
    virtual ~graph_adjmatrix() {};
    void addedges(int vertex1, int vertex2);
    void addedges(const std::vector<std::vector<T>> edges);
    void removeedges(int vertex1, int vertex2);
    void addvertexes(const std::vector<T> &vertexes);
    void removevertex(int index);
    void printf_graph();
};

template <typename T> graph_adjmatrix<T>::graph_adjmatrix(const std::vector<T> &vertexes, const std::vector<std::vector<T>> edges)
{
    int vertexes_num = vertexes.size();
    addvertexes(vertexes);
    addedges(edges);
}

template <typename T> void graph_adjmatrix<T>::addvertexes(const std::vector<T> &vertexes)
{
    int vertexes_num = vertexes.size();

    for (auto vertex : vertexes) {
        /* 将节点添加进顶点列表 */
        this->vertexes.push_back(vertex);
        /* 在邻接矩阵中添加一行 */
        this->adjmatrix.push_back(std::vector<T>(vertexes_num, 0));
        /* 每添加一个顶点，给每一列都增加一个成员 */
        for (std::vector<T> &row : adjmatrix) {
            row.push_back(0);
        }
    }
}

template <typename T> void graph_adjmatrix<T>::addedges(const std::vector<std::vector<T>> edges) { this->adjmatrix = edges; }

template <typename T> void graph_adjmatrix<T>::addedges(int vertex1, int vertex2)
{
    if (vertex1 < 0 || vertex2 < 0 || vertex1 == vertex2 || vertex1 >= this->vertexes.size() || vertex2 >= this->vertexes.size()) {
        return;
    }
    this->adjmatrix[vertex1][vertex2] = 1;
    this->adjmatrix[vertex2][vertex1] = 1;
}

template <typename T> void graph_adjmatrix<T>::removeedges(int vertex1, int vertex2)
{
    if (vertex1 < 0 || vertex2 < 0) {
        return;
    }
    this->adjmatrix[vertex1][vertex2] = 0;
    this->adjmatrix[vertex2][vertex1] = 1;
}

template <typename T> void graph_adjmatrix<T>::removevertex(int index)
{
    if (index < 0 || index >= this->vertexes.size()) {
        return;
    }

    /* 在顶点列表中移除相关的顶点 */
    this->vertexes.erase(this->vertexes.begin() + index);
    this->adjmatrix.erase(this->adjmatrix.begin() + index);

    for (auto &row : this->adjmatrix) {
        row.erase(row.begin() + index);
    }
}

template <typename T> void graph_adjmatrix<T>::printf_graph()
{
    using std::cout;
    cout << "顶点列表为:\n";
    for (const auto &vertex : this->vertexes) {
        cout << vertex << " ";
    }
    cout << "\n邻接表为:\n";

    for (const auto &row : this->adjmatrix) {
        for (const auto &vertex : row) {
            cout << vertex << " ";
        }
        cout << std::endl;
    }
    cout << std::endl;
}

#endif